<template>
  <div class="app-container">
    <el-row :gutter="20">
      <splitpanes class="default-theme">
        <!-- 结构树 -->
        <pane size="25">
          <div class="panel-container">
            <div class="panel-header">结构列表</div>
            <div class="search-box">
              <el-input
                v-model="structName"
                placeholder="请输入结构名称"
                clearable
                size="small"
                prefix-icon="el-icon-search" />
            </div>
            <div class="panel-body">
              <el-tree
                :data="structOptions"
                :props="defaultProps"
                :expand-on-click-node="false"
                :filter-node-method="filterStructNode"
                ref="structTree"
                node-key="id"
                default-expand-all
                highlight-current
                @node-click="handleStructNodeClick">
                <span class="tree-node-name" slot-scope="{ node, data }">
                  <i :class="data.isdir === 'Y' ? 'el-icon-folder' : 'el-icon-document'" class="node-icon"></i>
                  {{ node.label }}
                </span>
              </el-tree>
            </div>
          </div>
        </pane>

        <!-- 需求和技术指标区域 -->
        <pane size="75">
          <div class="content-container">
            <div class="panel-header">
              <span class="main-title">合同自动生成</span>
              <span class="sub-title" v-if="currentStruct">{{ currentStruct.name }}</span>
              <div class="header-actions">
                <el-button
                  type="primary"
                  icon="el-icon-document"
                  size="mini"
                  class="action-button"
                  @click="generateContract"
                  :disabled="!currentStruct || technicalIndicators.length === 0">
                  生成合同
                </el-button>
                <el-button
                  type="info"
                  icon="el-icon-refresh"
                  size="mini"
                  class="action-button expand-btn"
                  @click="refreshData"
                  :disabled="!currentStruct">
                  刷新数据
                </el-button>
              </div>
            </div>

            <!-- 需求和技术指标内容区域 -->
            <el-row :gutter="20" class="content-body">
              <!-- 需求列表 -->
              <el-col :span="12">
                <div class="requirements-panel">
                  <div class="section-header">
                    <i class="el-icon-tickets"></i>
                    <span>需求</span>
                    <el-tag type="info" size="small" class="count-tag">{{ demands.length }}</el-tag>
                  </div>
                  <div class="panel-content" v-loading="loadingRequirements">
                    <el-empty v-if="demands.length === 0" description="暂无需求数据"></el-empty>
                    <div v-else>
                      <!-- 使用分组显示需求 -->
                      <div v-for="(group, groupIndex) in demandGroups" :key="'demand-group-' + groupIndex" class="item-group">
                        <div class="group-header" @click="toggleGroupCollapse(group)">
                          <i :class="group.collapsed ? 'el-icon-arrow-right' : 'el-icon-arrow-down'" class="collapse-icon"></i>
                          <span class="group-title">{{ group.name }}</span>
                          <el-tag type="info" size="mini" class="group-count">{{ group.items.length }}</el-tag>
                        </div>
                        <div class="group-content" v-show="!group.collapsed">
                          <div class="requirements-text-boxes">
                            <div v-for="(demand, index) in group.items" :key="index" class="requirement-text-box" :class="{'numerical-input': demand.type === 'num'}">
                              <!-- 标准文本框显示 -->
                              <div v-if="demand.type !== 'num' && (!demand.options || demand.options.length <= 1)" class="requirement-display">
                                <span class="requirement-name">{{ demand.name }}:</span>
                                <span class="requirement-value">{{ demand.value || '无值' }}</span>
                              </div>

                              <!-- 下拉框显示多选项 -->
                              <div v-else-if="demand.type !== 'num' && demand.options && demand.options.length > 1" class="requirement-dropdown">
                                <span class="requirement-name">{{ demand.name }}:</span>
                                <el-select
                                  v-model="demand.selectedOption"
                                  placeholder="请选择选项"
                                  size="medium"
                                  @change="(val) => handleRequirementOptionChange(index, val)"
                                  class="requirement-select">
                                  <el-option
                                    v-for="option in demand.options"
                                    :key="option.value"
                                    :label="option.value"
                                    :value="option.value">
                                  </el-option>
                                </el-select>
                              </div>

                              <!-- 数值型输入显示 -->
                              <div v-else-if="demand.type === 'num'" class="requirement-numerical">
                                <span class="requirement-name">{{ demand.name }}:</span>
                                <div class="numerical-input-container">
                                  <el-input-number
                                    v-model="demand.inputValue"
                                    :min="getMinValue(demand)"
                                    :max="getMaxValue(demand)"
                                    :precision="3"
                                    :step="0.001"
                                    controls-position="right"
                                    size="medium"
                                    class="numerical-input">
                                  </el-input-number>

                                  <el-tooltip v-if="demand.formula" class="item" effect="dark" :content="`公式: ${demand.formula}`" placement="top">
                                    <i class="el-icon-info formula-info"></i>
                                  </el-tooltip>
                                </div>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </el-col>

              <!-- 转换按钮区域 - 居中放置 -->
              <div class="conversion-button-container">
                <div class="button-with-label">
                  <el-button
                    type="primary"
                    icon="el-icon-right"
                    class="conversion-button"
                    @click="convertToIndicators"
                    :disabled="!currentStruct || demands.length === 0">
                  </el-button>
                  <span class="button-label">转换</span>
                </div>
              </div>

              <!-- 技术指标列表 -->
              <el-col :span="12">
                <div class="indicators-panel">
                  <div class="section-header">
                    <i class="el-icon-data-analysis"></i>
                    <span>技术指标</span>
                    <el-tag type="info" size="small" class="count-tag">{{ technicalIndicators.length }}</el-tag>

                    <!-- 指标类型统计 -->
                    <div class="indicator-stats">
                      <el-tag type="info" size="mini" v-if="directMappingIndicators.length > 0">
                        直接映射: {{ directMappingIndicators.length }}
                      </el-tag>
                      <el-tag type="success" size="mini" v-if="knowledgeMappingIndicators.length > 0">
                        知识映射: {{ knowledgeMappingIndicators.length }}
                      </el-tag>
                      <el-tag type="warning" size="mini" v-if="calculatedIndicators.length > 0">
                        函数映射: {{ calculatedIndicators.length }}
                      </el-tag>
                    </div>
                  </div>

                  <!-- 技术指标面板内容 -->
                  <transition name="transform-panel">
                    <div class="panel-content" v-loading="loadingIndicators">
                      <el-empty v-if="technicalIndicators.length === 0" description="暂无技术指标数据"></el-empty>

                      <!-- 使用分组显示技术指标 -->
                      <div v-else>
                        <div v-for="(group, groupIndex) in indicatorGroups" :key="'indicator-group-' + groupIndex" class="item-group">
                          <div class="group-header" @click="toggleGroupCollapse(group)">
                            <i :class="group.collapsed ? 'el-icon-arrow-right' : 'el-icon-arrow-down'" class="collapse-icon"></i>
                            <span class="group-title">{{ group.name }}</span>
                            <el-tag type="info" size="mini" class="group-count">{{ group.items.length }}</el-tag>
                          </div>
                          <div class="group-content" v-show="!group.collapsed">
                            <transition-group name="indicator-transition" tag="div" class="requirements-text-boxes">
                              <div
                                v-for="(indicator, index) in group.items"
                                :key="indicator.id || index"
                                class="requirement-text-box indicator-box"
                                :class="{
                                  'direct-mapping': indicator.source === 'direct',
                                  'knowledge-mapping': indicator.source === 'knowledge',
                                  'calculation': indicator.source === 'calculation'
                                }">

                                <!-- 指标内容 -->
                                <div class="indicator-content">
                                  <div class="requirement-name">{{ indicator.name }}:</div>
                                  <div class="requirement-value">{{ indicator.value || '无值' }}</div>
                                  <el-tag size="mini" class="indicator-tag" :type="indicator.source === 'direct' ? 'info' : 'success'">
                                    {{ indicator.mappingType }}
                                  </el-tag>
                                </div>

                                <!-- 来源信息 - 所有指标都显示来源 -->
                                <div class="indicator-source">
                                  <span v-if="indicator.sources && indicator.sources.length > 1" class="source-info">
                                    <el-popover
                                      placement="top"
                                      width="300"
                                      trigger="hover">
                                      <div class="sources-popover">
                                        <div class="source-title">来源需求列表:</div>
                                        <div v-for="(source, idx) in indicator.sources" :key="idx" class="source-item">
                                          <span class="source-demand">{{ source.demand }}</span>
                                          <span v-if="source.value" class="source-value">值: {{ source.value }}</span>
                                          <el-tag size="mini" :type="source.source === 'direct' ? 'info' : (source.source === 'calculation' ? 'warning' : 'success')">
                                            {{ source.mappingType }}
                                          </el-tag>
                                        </div>
                                      </div>
                                      <span slot="reference" class="multiple-sources">
                                        来自: {{ indicator.multipleSourcesText }} <i class="el-icon-info"></i>
                                      </span>
                                    </el-popover>
                                  </span>
                                  <span v-else class="source-info">
                                    来自: {{ indicator.fromDemand || '未关联需求' }}
                                    {{ indicator.fromOption ? ' - ' + indicator.fromOption : '' }}
                                  </span>
                                </div>
                              </div>
                            </transition-group>
                          </div>
                        </div>
                      </div>
                    </div>
                  </transition>
                </div>
              </el-col>
            </el-row>

            <!-- 合同预览区域 -->
            <div class="contract-preview" v-if="showContractPreview">
              <div class="section-header">
                <i class="el-icon-document"></i>
                <span>合同预览</span>
                <div class="preview-actions">
                  <el-button
                    type="success"
                    size="mini"
                    icon="el-icon-download"
                    class="action-button add-btn"
                    @click="downloadContract">
                    下载合同
                  </el-button>
                </div>
              </div>
              <div class="preview-content">
                <div v-loading="generatingContract" class="contract-content">
                  <!-- 合同预览内容 -->
                  <div v-if="contractContent" v-html="contractContent" class="contract-html"></div>
                  <el-empty v-else description="暂无合同内容"></el-empty>
                </div>
              </div>
            </div>
          </div>
        </pane>
      </splitpanes>
    </el-row>

    <!-- 添加合同对话框 -->
    <el-dialog
      title="生成合同"
      :visible.sync="contractDialogVisible"
      width="600px"
      :close-on-click-modal="false">
      <el-form ref="contractForm" :model="contractForm" :rules="contractRules" label-width="120px">
        <el-form-item label="合同标题" prop="contractTitle">
          <el-input v-model="contractForm.contractTitle" placeholder="请输入合同标题"></el-input>
        </el-form-item>
        <el-form-item label="合同模板" prop="templatePath">
          <el-select v-model="contractForm.templatePath" placeholder="请选择合同模板" style="width: 100%">
            <el-option
              v-for="template in contractTemplates"
              :key="template.path"
              :label="template.name"
              :value="template.path">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="甲方" prop="partyA">
          <el-input v-model="contractForm.partyA" placeholder="请输入甲方名称"></el-input>
        </el-form-item>
        <el-form-item label="乙方" prop="partyB">
          <el-input v-model="contractForm.partyB" placeholder="请输入乙方名称"></el-input>
        </el-form-item>
        <el-form-item label="签订日期" prop="signDate">
          <el-date-picker
            v-model="contractForm.signDate"
            type="date"
            placeholder="选择签订日期"
            format="yyyy-MM-dd"
            value-format="yyyy-MM-dd">
          </el-date-picker>
        </el-form-item>
      </el-form>

      <div slot="footer" class="dialog-footer">
        <el-button @click="contractDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitContractForm" :loading="generating">确认生成</el-button>
      </div>
    </el-dialog>

    <!-- 生成成功提示对话框 -->
    <el-dialog
      title="合同生成成功"
      :visible.sync="successDialogVisible"
      width="400px"
      center>
      <div class="success-info">
        <div class="success-icon">
          <i class="el-icon-success"></i>
        </div>
        <div class="success-message">合同生成成功！</div>
        <div class="contract-info">
          <p><strong>合同编号：</strong>{{ generatedContract.contractNo }}</p>
          <p><strong>合同标题：</strong>{{ generatedContract.contractTitle }}</p>
          <p><strong>生成时间：</strong>{{ generatedContract.createTime }}</p>
          <p v-if="generatedContract.chainStatus"><strong>区块链状态：</strong>
            <el-tag :type="getChainStatusTagType(generatedContract.chainStatus)">
              {{ getChainStatusText(generatedContract.chainStatus) }}
            </el-tag>
          </p>
        </div>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="closeSuccessDialog">关闭</el-button>
        <el-button type="primary" @click="downloadGeneratedContract">下载合同</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import { Splitpanes, Pane } from "splitpanes";
import "splitpanes/dist/splitpanes.css";
import { listStruct } from "@/api/data/struct";
import { getDirectMappingBySid } from "@/api/data/direct_mapping";
import { getKnowledgeMappingResultsBySid, getKnowledgeMappingResultsByDoid } from "@/api/data/knowledge_mapping";
import { generateContract, downloadContract, listContractTemplates } from "@/api/contract/contract";
import { getFunctionMappingResultBySid } from "@/api/data/function_mapping";
import { getContractChainStatus, verifyContractChainData, uploadContractToChain } from "@/api/contract/contract";

export default {
  name: "ContractGenerate",
  components: { Splitpanes, Pane },
  data() {
    return {
      // 遮罩层
      loadingRequirements: false,
      loadingIndicators: false,
      generatingContract: false,

      // 结构树相关
      structName: undefined,
      structOptions: [],
      defaultProps: {
        children: "children",
        label: "name"
      },

      // 当前选中的结构节点
      currentStruct: null,

      // 需求和技术指标数据
      demands: [],
      technicalIndicators: [],

      // 合同预览相关
      showContractPreview: false,
      contractContent: null,

      // 知识映射相关
      knowledgeMappingLoading: false,
      knowledgeMappingList: [],

      // 当前选中的映射
      selectedMappings: [],

      // 分开存储两种映射的技术指标
      directMappingIndicators: [], // 直接映射的指标
      knowledgeMappingIndicators: [], // 知识映射的指标

      // 合并后的所有技术指标
      technicalIndicators: [],

      // 显示控制
      showDirectMappings: true,
      showKnowledgeMappings: true,

      // 合同对话框相关
      contractDialogVisible: false,
      successDialogVisible: false,
      generating: false,
      contractForm: {
        contractTitle: "",
        partyA: "",
        partyB: "",
        signDate: "",
        structId: "",
        structName: "",
        indicatorsJson: "",
        templatePath: "" // 新增模板路径字段
      },
      contractRules: {
        contractTitle: [
          { required: true, message: "请输入合同标题", trigger: "blur" }
        ],
        partyA: [
          { required: true, message: "请输入甲方名称", trigger: "blur" }
        ],
        partyB: [
          { required: true, message: "请输入乙方名称", trigger: "blur" }
        ],
        signDate: [
          { required: true, message: "请选择签订日期", trigger: "change" }
        ],
        templatePath: [
          { required: true, message: "请选择合同模板", trigger: "change" }
        ]
      },
      // 合同模板列表
      contractTemplates: [],
      generatedContract: {},

      // Add new properties for numerical mappings
      numericalMappings: [], // Store the numerical mappings
      calculatedIndicators: [], // Store the calculated indicators

      // 添加：对需求进行分组
      demandGroups: [],

      // 添加：对技术指标进行分组
      indicatorGroups: [],

      // 链上状态相关
      chainStatusTimer: null,
      chainStatusLoading: false,
    };
  },
  watch: {
    structName(val) {
      this.$refs.structTree.filter(val);
    }
  },
  created() {
    this.getStructList();
    this.getContractTemplates();
  },
  methods: {
    // 获取合同模板列表
    getContractTemplates() {
      listContractTemplates().then(response => {
        this.contractTemplates = response.data || [];
        // 如果没有模板，添加一个默认模板
        if (this.contractTemplates.length === 0) {
          this.contractTemplates = [
            {
              name: "默认模板",
              path: "contract/templates/contract_template.docx"
            }
          ];
        }
      }).catch(() => {
        // 如果接口调用失败，使用默认模板
        this.contractTemplates = [
          {
            name: "默认模板",
            path: "contract/templates/contract_template.docx"
          }
        ];
        this.$message.warning("获取合同模板列表失败，使用默认模板");
      });
    },

    // 获取结构列表
    getStructList() {
      listStruct().then(response => {
        this.structOptions = this.handleTree(response.data, "id", "pid");
      });
    },

    // 筛选结构树节点
    filterStructNode(value, data) {
      if (!value) return true;
      return data.name.indexOf(value) !== -1;
    },

    // 点击结构树节点
    handleStructNodeClick(data) {
      console.log("结构节点被点击:", data);
      // 设置当前结构，无论是否为目录
      this.currentStruct = data;

      // 清空现有数据
      this.demands = [];
      this.directMappingIndicators = [];
      this.knowledgeMappingIndicators = [];
      this.calculatedIndicators = []; // Clear calculated indicators
      this.technicalIndicators = [];

      // 加载该节点下的需求数据和知识映射数据 - 不立即加载直接映射
      this.loadRequirementsData(data.id);
      this.loadKnowledgeMappingData(data.id);
      this.loadNumericalMappings(data.id); // Add this line to load numerical mappings
    },

    // 加载需求数据
    loadRequirementsData(structId) {
      console.log("加载需求数据, structId:", structId);
      this.loadingRequirements = true;
      this.demands = [];
      this.technicalIndicators = [];
      this.showContractPreview = false;
      this.contractContent = null;

      // 使用getDirectMappingBySid获取需求数据
      getDirectMappingBySid(structId).then(response => {
        console.log("获取到映射数据:", response.data);
        const mappings = response.data || [];

        // 使用Map存储需求，以需求名称为键，确保唯一性
        const uniqueDemands = new Map();

        // 直接将映射数据转化为需求列表，并去重
        if (mappings && mappings.length > 0) {
          mappings.forEach(mapping => {
            // 确保有需求名称才添加
            if (mapping.demandName) {
              const demandKey = mapping.demandName;

              // 如果需求名称还不存在，则添加到Map中
              if (!uniqueDemands.has(demandKey)) {
                uniqueDemands.set(demandKey, {
                  id: mapping.id,
                  name: mapping.demandName || '未命名需求',
                  type: mapping.demandType || 'text',
                  value: mapping.demandValue || '',
                  description: mapping.demandDescription || '',
                  isMapped: true,
                  // 添加父节点信息
                  demandParentName: mapping.demandParentName || '未分类'
                });
              }
            }
          });
        }

        // 将Map转换为数组
        this.demands = Array.from(uniqueDemands.values());

        console.log("处理后的需求数据:", this.demands);

        // 添加分组处理
        this.groupDemandsByName();

        this.loadingRequirements = false;
      }).catch(error => {
        console.error("获取映射数据失败:", error);
        this.loadingRequirements = false;
        this.$message.error("获取需求数据失败");
      });
    },

    // 加载知识映射数据
    loadKnowledgeMappingData(structId) {
      if (!structId) return;

      this.knowledgeMappingLoading = true;
      this.knowledgeMappingList = [];

      getKnowledgeMappingResultsBySid(structId).then(response => {
        console.log("获取到知识映射数据:", response.data);

        // 将获取到的知识映射数据保存
        this.knowledgeMappingList = response.data || [];

        // 处理知识映射数据，按需求和指标进行分组
        this.processKnowledgeMappingData();

        this.knowledgeMappingLoading = false;
      }).catch(error => {
        console.error("获取知识映射数据失败:", error);
        this.knowledgeMappingLoading = false;
        this.$message.error("获取知识映射数据失败");
      });
    },

    // 处理知识映射数据，将其按需求和指标进行分组
    processKnowledgeMappingData() {
      const groupedMappings = {};

      // 按需求名称分组
      this.knowledgeMappingList.forEach(item => {
        if (!item.demandName) return;

        const demandKey = item.demandName;
        if (!groupedMappings[demandKey]) {
          groupedMappings[demandKey] = {
            id: `demand_${item.doid || new Date().getTime()}`,
            name: item.demandName,
            type: item.demandType || 'option',
            options: [],
            selectedOption: null,
            selectedDoid: null,
            isMapped: true,
            mappingSource: 'knowledge',
            // 添加父节点信息
            demandParentName: item.demandParentName || '未分类'
          };
        }

        // 添加选项，确保包含doid信息
        const optionValue = item.demandOptionValue || item.demandValue;
        if (optionValue && !groupedMappings[demandKey].options.find(opt => opt.value === optionValue)) {
          groupedMappings[demandKey].options.push({
            value: optionValue,
            doid: item.doid,
            indicatorName: item.indicatorName,
            indicatorValue: item.indicatorOptionValue || item.indicatorValue
          });

          // 默认选择第一个选项
          if (!groupedMappings[demandKey].selectedOption) {
            groupedMappings[demandKey].selectedOption = optionValue;
            groupedMappings[demandKey].selectedDoid = item.doid;
          }
        }
      });

      // 转换为需求列表格式
      const processedMappings = Object.values(groupedMappings);
      console.log("处理后的知识映射数据:", processedMappings);

      // 将处理后的映射结果添加到需求列表中，但要检查是否已存在同名需求
      processedMappings.forEach(mapping => {
        // 确保有需求名称和选项才添加
        if (mapping.name && mapping.options.length > 0) {
          // 检查是否已存在同名需求
          const existingDemandIndex = this.demands.findIndex(d => d.name === mapping.name);

          if (existingDemandIndex === -1) {
            // 不存在同名需求，直接添加
            this.demands.push(mapping);
          } else {
            // 存在同名需求，根据情况进行处理
            // 如果现有需求没有选项，而当前映射有选项，则优先使用当前映射
            const existingDemand = this.demands[existingDemandIndex];
            if (!existingDemand.options || existingDemand.options.length === 0) {
              // 用新的映射替换旧的需求
              this.demands[existingDemandIndex] = mapping;
            }
            // 如果两者都有选项，则保留现有需求，不做替换
          }
        }
      });

      // 添加：对需求进行分组
      this.groupDemandsByName();
    },

    // 当需求选项变更时
    handleRequirementOptionChange(demandIndex, newValue) {
      const demand = this.demands[demandIndex];
      demand.selectedOption = newValue;

      // 查找选中选项对应的doid
      const selectedOption = demand.options.find(opt => opt.value === newValue);
      if (selectedOption && selectedOption.doid) {
        demand.selectedDoid = selectedOption.doid;
        console.log(`需求 "${demand.name}" 选项已更改为: ${newValue}, doid: ${selectedOption.doid}`);

        // 选择选项后立即加载对应的技术指标 (可选，取消注释启用即时加载)
        // this.loadIndicatorsByDoid(selectedOption.doid);
      }
    },

    // 根据需求选项ID加载技术指标
    loadIndicatorsByDoid(doid) {
      this.loadingIndicators = true;
      this.technicalIndicators = []; // Clear existing indicators

      getKnowledgeMappingResultsByDoid(doid).then(response => {
        console.log("根据doid获取到的映射数据:", response.data);

        if (response.data && response.data.length > 0) {
          // 处理返回的技术指标数据
          const uniqueIndicators = new Map(); // 使用Map去重

          response.data.forEach(item => {
            // 确保指标名称存在
            if (item.indicatorName) {
              const indicatorKey = `${item.indicatorName}_${item.indicatorOptionValue || item.indicatorValue || ''}`;

              if (!uniqueIndicators.has(indicatorKey)) {
                // 添加新的技术指标
                uniqueIndicators.set(indicatorKey, {
                  id: item.ioid || item.id,
                  name: item.indicatorName,
                  type: item.indicatorType || 'text',
                  value: item.indicatorOptionValue || item.indicatorValue || '',
                  source: 'mapping'
                });
              }
            }
          });

          // 转换为数组
          this.technicalIndicators = Array.from(uniqueIndicators.values());

          if (this.technicalIndicators.length > 0) {
            this.$message.success(`已加载 ${this.technicalIndicators.length} 个技术指标`);
          } else {
            this.$message.warning("未找到关联的技术指标");
          }
        } else {
          this.$message.warning("未找到关联的技术指标");
        }

        this.loadingIndicators = false;
      }).catch(error => {
        console.error("获取技术指标失败:", error);
        this.loadingIndicators = false;
        this.$message.error("获取技术指标失败");
      });
    },

    // 将需求转换为技术指标
    convertToIndicators() {
      if (!this.currentStruct) {
        this.$message.warning("请先选择一个结构");
        return;
      }

      this.loadingIndicators = true;

      // 立即同步所有输入框值到数据模型中
      this.syncInputValues();
      console.log("转换前输入值已同步:", this.numericalMappings.map(m => ({
        name: m.name,
        inputValue: m.inputValue
      })));

      // 计算数值型指标
      this.calculateNumericalIndicators();

      // 先获取直接映射，然后获取知识映射
      Promise.all([
        this.fetchDirectMappings(),
        this.fetchKnowledgeMappings()
      ])
        .then(([directMappings, knowledgeMappings]) => {
          const totalIndicators = directMappings.length + knowledgeMappings.length + this.calculatedIndicators.length;

          if (totalIndicators > 0) {
            this.$message.success(
              `已获取 ${totalIndicators} 个技术指标 ` +
              `(直接映射: ${directMappings.length}, ` +
              `知识映射: ${knowledgeMappings.length}, ` +
              `函数映射: ${this.calculatedIndicators.length})`
            );
          } else {
            this.$message.warning("未找到任何技术指标");
          }
        })
        .finally(() => {
          this.loadingIndicators = false;
        });
    },

    // 刷新数据
    refreshData() {
      if (!this.currentStruct) {
        this.$message.warning("请先选择一个结构");
        return;
      }

      // Clear existing data
      this.demands = [];
      this.directMappingIndicators = [];
      this.knowledgeMappingIndicators = [];
      this.calculatedIndicators = [];
      this.technicalIndicators = [];

      // Reload all data
      this.loadRequirementsData(this.currentStruct.id);
      this.loadKnowledgeMappingData(this.currentStruct.id);
      this.loadNumericalMappings(this.currentStruct.id);

      this.$message.success("数据已刷新");
    },

    // 生成合同
    generateContract() {
      if (!this.currentStruct) {
        this.$message.warning("请先选择结构");
        return;
      }

      if (this.technicalIndicators.length === 0) {
        this.$message.warning("当前结构没有技术指标，无法生成合同");
        return;
      }

      // 检查是否有可用的合同模板
      if (this.contractTemplates.length === 0) {
        this.$message.warning("没有可用的合同模板，请先添加模板");
        return;
      }

      // 初始化表单 - 确保 structId 处理为字符串
      this.contractForm = {
        contractTitle: this.currentStruct.name + "技术协议",
        partyA: "贵公司",
        partyB: "本公司",
        signDate: new Date().toISOString().substr(0, 10),
        structId: this.currentStruct.id.toString(),
        structName: this.currentStruct.name,
        indicatorsJson: JSON.stringify(this.technicalIndicators),
        templatePath: "" // 初始化为空,让用户在对话框中选择
      };

      // 显示对话框
      this.contractDialogVisible = true;
    },

    // 提交合同表单
    submitContractForm() {
      this.$refs.contractForm.validate(valid => {
        if (valid) {
          this.generating = true;

          generateContract(this.contractForm).then(response => {
            this.generating = false;
            this.contractDialogVisible = false;

            // 保存生成的合同信息
            this.generatedContract = response.data;

            // 显示成功对话框
            this.successDialogVisible = true;
            
            // 启动链上状态轮询
            this.startChainStatusPolling();
          }).catch(error => {
            this.generating = false;
            console.error("生成合同失败:", error);

            // 提取更详细的错误信息
            let errorMsg = "未知错误";
            if (error.response && error.response.data) {
              errorMsg = error.response.data.message || error.response.data;
            } else if (error.message) {
              errorMsg = error.message;
            }

            this.$message.error({
              message: "生成合同失败: " + errorMsg,
              duration: 5000
            });
          });
        }
      });
    },
    
    // 启动链上状态轮询
    startChainStatusPolling() {
      // 清除现有定时器
      if (this.chainStatusTimer) {
        clearInterval(this.chainStatusTimer);
      }
      
      // 检查是否有合同编号
      if (!this.generatedContract || !this.generatedContract.contractNo) {
        return;
      }
      
      // 立即查询一次
      this.refreshChainStatus();
      
      // 设置定时器，每5秒刷新一次状态，直到关闭对话框或状态变为CONFIRMED
      this.chainStatusTimer = setInterval(() => {
        // 如果对话框已关闭或状态已确认，停止轮询
        if (!this.successDialogVisible || 
            (this.generatedContract.chainStatus && this.generatedContract.chainStatus === 'CONFIRMED')) {
          clearInterval(this.chainStatusTimer);
          return;
        }
        
        this.refreshChainStatus();
      }, 5000);
    },
    
    // 刷新链上状态
    refreshChainStatus() {
      if (this.chainStatusLoading || !this.generatedContract.contractNo) {
        return;
      }
      
      this.chainStatusLoading = true;
      getContractChainStatus(this.generatedContract.contractNo)
        .then(response => {
          this.chainStatusLoading = false;
          if (response.code === 200 && response.data) {
            // 更新链上状态
            this.generatedContract.chainStatus = response.data.chainStatus;
            this.generatedContract.txHash = response.data.txHash;
            this.generatedContract.chainTime = response.data.chainTime;
            this.generatedContract.chainCertNo = response.data.chainCertNo;
            
            // 如果状态已确认，停止轮询
            if (this.generatedContract.chainStatus === 'CONFIRMED') {
              clearInterval(this.chainStatusTimer);
            }
          }
        })
        .catch(error => {
          this.chainStatusLoading = false;
          console.error("获取链上状态失败:", error);
        });
    },
    
    // 手动上链
    manualUploadToChain() {
      if (!this.generatedContract || !this.generatedContract.contractNo) {
        this.$message.warning("没有可上链的合同");
        return;
      }
      
      if (this.generatedContract.chainStatus === 'CONFIRMED') {
        this.$message.info("该合同已成功上链，无需重复操作");
        return;
      }
      
      this.$confirm("确定要将该合同上传到区块链吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        this.chainStatusLoading = true;
        uploadContractToChain(this.generatedContract.contractNo)
          .then(response => {
            this.chainStatusLoading = false;
            if (response.code === 200) {
              this.$message.success("上链请求已提交");
              // 更新状态
              this.refreshChainStatus();
              // 重启轮询
              this.startChainStatusPolling();
            } else {
              this.$message.error(response.msg || "上链失败");
            }
          })
          .catch(error => {
            this.chainStatusLoading = false;
            this.$message.error("上链失败: " + error.message);
          });
      }).catch(() => {});
    },
    
    // 关闭成功对话框
    closeSuccessDialog() {
      this.successDialogVisible = false;
      // 清除轮询
      if (this.chainStatusTimer) {
        clearInterval(this.chainStatusTimer);
        this.chainStatusTimer = null;
      }
    },

    // 下载生成的合同
    downloadGeneratedContract() {
      this.downloadContract(this.generatedContract.contractNo);
    },

    // 通用下载方法
    downloadContract(contractNo) {
      this.$message.info("开始下载合同...");

      downloadContract(contractNo).then(response => {
        // 创建Blob对象
        const blob = new Blob([response], {
          type: 'application/octet-stream'
        });

        // 创建临时下载链接
        const link = document.createElement('a');
        link.href = window.URL.createObjectURL(blob);
        link.download = contractNo + '.docx';
        link.click();

        // 清理临时链接
        window.URL.revokeObjectURL(link.href);

        this.$message.success("合同下载成功");
      }).catch(error => {
        console.error("下载合同失败:", error);
        this.$message.error("下载合同失败");
      });
    },

    // 获取类型名称
    getTypeName(type) {
      const typeMap = {
        'text': '文本',
        'num': '数字',
        'range': '范围',
        'option': '选项'
      };
      return typeMap[type] || type;
    },

    // 获取类型标签样式
    getTypeTagType(type) {
      const typeTagMap = {
        'text': 'success',
        'num': 'primary',
        'range': 'warning',
        'option': 'info'
      };
      return typeTagMap[type] || '';
    },

    // 获取并处理直接映射
    fetchDirectMappings() {
      if (!this.currentStruct || !this.currentStruct.id) {
        return Promise.resolve([]);
      }

      this.loadingIndicators = true;

      // 调用直接映射的API
      return getDirectMappingBySid(this.currentStruct.id)
        .then(response => {
          console.log("直接映射原始数据:", response.data);

          if (response.data && response.data.length > 0) {
            // 转换为指标格式，确保保留父节点名称
            this.directMappingIndicators = response.data
              .filter(item => item.indicatorName || item.technicalName) // 确保有指标名称
              .map(item => ({
                id: item.id,
                name: item.indicatorName || item.technicalName || item.name,
                type: item.indicatorType || item.type || 'text',
                value: item.indicatorValue || item.technicalValue || item.value || '',
                source: 'direct',
                mappingType: '直接映射',
                // 添加需求关联信息
                fromDemand: item.demandName || '未命名需求',
                fromValue: item.demandValue || '',
                // 保留父节点信息
                indicatorParentName: item.indicatorParentName,
                demandParentName: item.demandParentName,
                indicatorPid: item.indicatorPid,
                demandPid: item.demandPid,
                indicatorIsdir: item.indicatorIsdir,
                demandIsdir: item.demandIsdir
              }));

            console.log(`获取到 ${this.directMappingIndicators.length} 个直接映射指标:`, this.directMappingIndicators);
          } else {
            this.directMappingIndicators = [];
            console.log('未找到直接映射指标');
          }

          // 确保更新技术指标列表
          this.updateTechnicalIndicators();
          return this.directMappingIndicators;
        })
        .catch(error => {
          console.error('获取直接映射失败:', error);
          this.$message.error('获取直接映射失败');
          this.directMappingIndicators = [];

          // 即使失败也更新技术指标列表
          this.updateTechnicalIndicators();
          return [];
        })
        .finally(() => {
          this.loadingIndicators = false;
        });
    },

    // 根据选中的需求选项获取知识映射
    fetchKnowledgeMappings() {
      if (!this.currentStruct || this.demands.length === 0) {
        return Promise.resolve([]);
      }

      // 获取所有选中选项的doid
      const selectedDemands = this.demands.filter(demand =>
        demand.options && demand.options.length > 0 && demand.selectedOption && demand.selectedDoid
      );

      if (selectedDemands.length === 0) {
        console.log('未选择任何需求选项，使用默认选项');

        // 使用默认选项 - 对于每个有选项的需求，使用第一个选项
        const demandsWithOptions = this.demands.filter(demand =>
          demand.options && demand.options.length > 0
        );

        demandsWithOptions.forEach(demand => {
          if (!demand.selectedOption && demand.options.length > 0) {
            demand.selectedOption = demand.options[0].value;
            demand.selectedDoid = demand.options[0].doid;
          }
        });

        // 更新选中的需求
        return this.fetchKnowledgeMappings();
      }

      console.log("已选中的需求选项:", selectedDemands.map(demand => ({
        name: demand.name,
        selectedOption: demand.selectedOption,
        doid: demand.selectedDoid
      })));

      // 清空现有知识映射指标
      this.knowledgeMappingIndicators = [];

      // 使用Promise.all并行处理所有选中选项的doid请求
      const promises = selectedDemands.map(demand =>
        getKnowledgeMappingResultsByDoid(demand.selectedDoid).then(response => {
          return { demand, response };
        })
      );

      return Promise.all(promises)
        .then(results => {
          // 处理所有返回的结果
          results.forEach(({ demand, response }) => {
            console.log(`需求 "${demand.name}" 选项 "${demand.selectedOption}" 原始映射数据:`, response.data);

            if (response.data && response.data.length > 0) {
              console.log(`需求 "${demand.name}" 选项 "${demand.selectedOption}" 获取到 ${response.data.length} 个映射结果`);

              // 为每个响应数据添加一个单独的指标，确保保留父节点名称
              response.data.forEach(item => {
                // 确保指标名称存在
                if (item.indicatorName || item.indicator_name) {
                  this.knowledgeMappingIndicators.push({
                    id: item.ioid || item.id || `km_${Date.now()}_${Math.random()}`,
                    name: item.indicatorName || item.indicator_name,
                    type: item.indicatorType || item.indicator_type || 'text',
                    value: item.indicatorOptionValue || item.indicator_option_value || item.indicatorValue || '',
                    source: 'knowledge',
                    mappingType: '知识映射',
                    fromDemand: demand.name,
                    fromOption: demand.selectedOption,
                    // 保留父节点信息 - 确保所有可能的字段名称都被考虑
                    indicatorParentName: item.indicatorParentName || item.indicator_parent_name,
                    demandParentName: item.demandParentName || item.demand_parent_name,
                    indicatorPid: item.indicatorPid || item.indicator_pid,
                    demandPid: item.demandPid || item.demand_pid,
                    indicatorIsdir: item.indicatorIsdir || item.indicator_isdir,
                    demandIsdir: item.demandIsdir || item.demand_isdir
                  });
                }
              });
            } else {
              console.log(`需求 "${demand.name}" 选项 "${demand.selectedOption}" 未找到映射结果`);
            }
          });

          console.log(`获取到 ${this.knowledgeMappingIndicators.length} 个知识映射指标:`, this.knowledgeMappingIndicators);

          // 更新合并后的技术指标列表
          this.updateTechnicalIndicators();

          return this.knowledgeMappingIndicators;
        })
        .catch(error => {
          console.error("获取知识映射指标失败:", error);
          this.$message.error("获取知识映射指标失败");
          this.knowledgeMappingIndicators = [];

          // 更新合并后的技术指标列表
          this.updateTechnicalIndicators();

          return [];
        })
        .finally(() => {
          this.loadingIndicators = false;
        });
    },

    // 更新合并后的技术指标列表
    updateTechnicalIndicators() {
      // 使用Map来去重，以指标名称为键
      const uniqueIndicators = new Map();

      // 处理所有类型的指标
      const allIndicators = [
        ...this.directMappingIndicators,
        ...this.knowledgeMappingIndicators,
        ...this.calculatedIndicators
      ];

      // 按名称合并指标
      allIndicators.forEach(indicator => {
        const key = indicator.name;

        if (!uniqueIndicators.has(key)) {
          // 第一次遇到这个名称，直接添加
          uniqueIndicators.set(key, {
            ...indicator,
            sources: indicator.sources || [{
              demand: indicator.fromDemand || '未知',
              value: indicator.fromValue || indicator.value || '',
              source: indicator.source,
              mappingType: indicator.mappingType
            }]
          });
        } else {
          // 已存在同名指标，合并来源信息
          const existingIndicator = uniqueIndicators.get(key);

          // 确保sources数组存在
          if (!existingIndicator.sources) {
            existingIndicator.sources = [{
              demand: existingIndicator.fromDemand || '未知',
              value: existingIndicator.fromValue || existingIndicator.value || '',
              source: existingIndicator.source,
              mappingType: existingIndicator.mappingType
            }];
          }

          // 添加新的来源
          existingIndicator.sources.push({
            demand: indicator.fromDemand || '未知',
            value: indicator.fromValue || indicator.value || '',
            source: indicator.source,
            mappingType: indicator.mappingType
          });

          // 优先保留非直接映射的指标设置
          if (indicator.source !== 'direct' && existingIndicator.source === 'direct') {
            existingIndicator.source = indicator.source;
            existingIndicator.mappingType = indicator.mappingType;
          }

          // 更新该指标的来源文本
          existingIndicator.multipleSourcesText = `${existingIndicator.sources.length} 个需求`;
        }
      });

      // 将Map转换回数组
      this.technicalIndicators = Array.from(uniqueIndicators.values());

      // 确保合并后的指标正确显示多个来源
      this.technicalIndicators.forEach(indicator => {
        // 如果有多个来源，更新显示的来源文本
        if (indicator.sources && indicator.sources.length > 1) {
          indicator.multipleSourcesText = `${indicator.sources.length} 个需求`;
        }

        // 确保计算型指标具有正确的样式类型
        if (indicator.source === 'calculation') {
          indicator.mappingType = '函数映射';
        }
      });

      // 添加：对技术指标进行分组
      this.groupIndicatorsByName();

      console.log(`技术指标总数: ${this.technicalIndicators.length}`);
      console.log(`- 直接映射: ${this.directMappingIndicators.length}`);
      console.log(`- 知识映射: ${this.knowledgeMappingIndicators.length}`);
      console.log(`- 公式计算: ${this.calculatedIndicators.length}`);
      console.log(`- 合并后: ${this.technicalIndicators.length} (去重后)`);
    },

    // 添加：根据名称对需求进行分组
    groupDemandsByName() {
      // 创建分组数据结构
      this.demandGroups = [];
      const groupMap = {};

      console.log("分组前的需求数据:", JSON.stringify(this.demands.map(d => ({
        name: d.name,
        parentName: d.demandParentName
      }))));

      // 根据父节点名称进行分组
      this.demands.forEach(demand => {
        // 使用父节点名称作为分组依据
        const groupName = demand.demandParentName || '未分类';

        if (!groupMap[groupName]) {
          groupMap[groupName] = {
            name: groupName,
            collapsed: false,
            items: []
          };
          this.demandGroups.push(groupMap[groupName]);
        }

        groupMap[groupName].items.push(demand);
      });

      // 对分组进行排序
      this.demandGroups.sort((a, b) => a.name.localeCompare(b.name));

      console.log("需求分组结果:", this.demandGroups);
    },

    // 添加：根据名称对技术指标进行分组
    groupIndicatorsByName() {
      // 创建分组数据结构
      this.indicatorGroups = [];
      const groupMap = {};

      console.log("分组前的技术指标数据:", JSON.stringify(this.technicalIndicators.map(i => ({
        name: i.name,
        parentName: i.indicatorParentName,
        source: i.source
      }))));

      // 根据父节点名称进行分组
      this.technicalIndicators.forEach(indicator => {
        // 使用父节点名称作为分组依据
        const groupName = indicator.indicatorParentName || '未分类';

        if (!groupMap[groupName]) {
          groupMap[groupName] = {
            name: groupName,
            collapsed: false,
            items: []
          };
          this.indicatorGroups.push(groupMap[groupName]);
        }

        groupMap[groupName].items.push(indicator);
      });

      // 对分组进行排序
      this.indicatorGroups.sort((a, b) => a.name.localeCompare(b.name));

      console.log("技术指标分组结果:", this.indicatorGroups);
    },

    // 添加：切换分组折叠状态
    toggleGroupCollapse(group) {
      group.collapsed = !group.collapsed;
    },

    // 加载数值型映射数据
    loadNumericalMappings(structId) {
      if (!structId) return;

      // 使用函数映射API获取数值型映射数据
      getFunctionMappingResultBySid(structId).then(response => {
        console.log("获取到函数映射数据:", response.data);

        // 处理函数映射数据
        this.numericalMappings = (response.data || []).map(mapping => ({
          id: mapping.id,
          name: mapping.demandName || '数值需求',
          type: 'num',
          value: mapping.demandValue || '',
          description: mapping.description || '',
          formula: mapping.formula || '',
          unit: mapping.unit || '',
          inputValue: mapping.demandValue || 0, // 默认用需求值，如果没有则为0
          sdid: mapping.sdid, // 存储需求ID
          siid: mapping.siid, // 存储指标ID
          indicatorName: mapping.indicatorName || mapping.technicalName || mapping.name, // 保存技术指标名
          variable: mapping.variable || '', // 添加变量名称字段
          // 保留父节点信息
          indicatorParentName: mapping.indicatorParentName,
          demandParentName: mapping.demandParentName,
          // 保存这些信息以确保分组正确
          isMapped: true
        }));

        // 将数值型映射添加到需求列表中，但要检查是否已存在同名需求
        this.numericalMappings.forEach(mapping => {
          // 检查是否已存在同名需求
          const existingDemandIndex = this.demands.findIndex(d => d.name === mapping.name);

          if (existingDemandIndex === -1) {
            // 不存在同名需求，直接添加
            this.demands.push(mapping);
          } else {
            // 存在同名需求，根据情况进行处理
            // 如果现有需求不是数值类型，而当前映射是数值类型，则优先使用当前映射
            const existingDemand = this.demands[existingDemandIndex];
            if (existingDemand.type !== 'num' && mapping.type === 'num') {
              // 用新的映射替换旧的需求
              this.demands[existingDemandIndex] = mapping;
            }
            // 如果两者都是数值类型，则保留现有需求，不做替换
          }
        });

        // 添加：对需求进行分组 - 确保新添加的数值需求也被分组
        this.groupDemandsByName();

        console.log("处理后的函数映射需求:", this.numericalMappings);
      }).catch(error => {
        console.error("获取函数映射数据失败:", error);
        this.$message.error("获取函数映射数据失败");
      });
    },

    // 计算数值型指标
    calculateNumericalIndicators() {
      this.calculatedIndicators = [];

      // 查找含有公式的映射
      const mappingsWithFormulas = this.numericalMappings.filter(
        mapping => mapping.formula && mapping.formula.trim() !== ''
      );

      if (mappingsWithFormulas.length === 0) {
        console.log("没有找到包含公式的函数映射");
        return;
      }

      // 先同步所有输入值
      this.syncInputValues();

      // 按函数映射分组，相同的siid视为一组
      const mappingGroups = {};
      mappingsWithFormulas.forEach(mapping => {
        const key = mapping.siid || 'default';
        if (!mappingGroups[key]) {
          mappingGroups[key] = [];
        }
        mappingGroups[key].push(mapping);
      });

      // 处理每个函数映射组
      Object.entries(mappingGroups).forEach(([siid, group]) => {
        try {
          // 只取每个siid组的第一个映射来获取公式和cnt
          const referenceDemand = group[0];
          const formula = referenceDemand.formula;
          const cnt = parseInt(referenceDemand.cnt) || group.length;

          // 检查变量数量是否足够
          if (group.length < cnt) {
            console.log(`变量数量不足 (${group.length}/${cnt})，跳过计算`);
            return;
          }

          // 收集需要的变量值 - 只取前cnt个
          const variableValues = {};

          // 只使用前cnt个需求的变量
          for (let i = 0; i < cnt; i++) {
            const demand = group[i];
            // 修复bug: 使用数据库中指定的变量名或回退到序号变量名
            // 优先使用从数据库获取的变量名
            const varName = demand.variable && demand.variable.trim() !== ''
                            ? demand.variable.trim()
                            : `x${i+1}`;

            // 支持小数输入, 适当处理NaN情况
            const inputValue = parseFloat(demand.inputValue);
            variableValues[varName] = isNaN(inputValue) ? 0 : inputValue;

            // 调试输出变量名和对应的值
            console.log(`变量 ${varName} = ${variableValues[varName]}, 来自需求: ${demand.name}`);
          }

          // 创建安全的计算函数
          const calcFunction = new Function('variables', `
            try {
              with (variables) {
                with (Math) {
                  return ${formula};
                }
              }
            } catch (error) {
              console.error("计算公式执行错误:", error, "公式:", "${formula}", "变量:", JSON.stringify(variables));
              return 0;
            }
          `);

          // 执行计算 - 每个siid组只计算一次
          const result = calcFunction(variableValues);

          // 输出调试信息
          console.log(`计算公式: ${formula}`, `变量:`, variableValues, `结果:`, result);

          // 格式化结果 - 改进:保留更多小数位数,处理无穷大情况
          let formattedResult;

          if (!isFinite(result)) {
            // 处理无穷大值
            formattedResult = result > 0 ? '∞' : '-∞';
          } else if (isNaN(result)) {
            // 处理NaN
            formattedResult = '计算错误';
          } else {
            // 保留更多小数位数，但移除尾部多余的0
            formattedResult = parseFloat(result.toFixed(4)).toString();
          }

          // 获取用于显示的需求列表 - 只显示参与计算的需求
          const usedDemands = group.slice(0, cnt);

          // 创建技术指标对象 - 每个siid组只创建一个指标
          const calculatedIndicator = {
            id: `calc_${siid}`,
            name: referenceDemand.indicatorName || '计算指标',
            type: 'num',
            value: `${formattedResult}${referenceDemand.unit ? ' ' + referenceDemand.unit : ''}`,
            source: 'calculation',
            mappingType: '函数映射',
            formula: formula,
            fromDemand: usedDemands.map(m => m.name).join(', '),
            fromValue: Object.entries(variableValues).map(([k, v]) => {
              // 改进:处理无穷大的显示
              if (!isFinite(v)) {
                return `${k}=${v > 0 ? '∞' : '-∞'}`;
              }
              return `${k}=${v}`;
            }).join(', '),
            // 保存分组所需的父节点信息
            indicatorParentName: referenceDemand.indicatorParentName,
            demandParentName: referenceDemand.demandParentName,
            sources: usedDemands.map(demand => ({
              demand: demand.name,
              value: demand.inputValue,
              source: 'calculation',
              mappingType: '函数映射'
            }))
          };

          this.calculatedIndicators.push(calculatedIndicator);
        } catch (error) {
          console.error(`处理函数映射组失败:`, error);
          //this.$message.error(`计算函数映射组时出错: ${error.message}`);
        }
      });

      // 更新技术指标数组
      this.updateTechnicalIndicators();
    },

    // 同步输入值到所有映射
    syncInputValues() {
      // 确保numericalMappings存在
      if (!this.numericalMappings || this.numericalMappings.length === 0) {
        return;
      }

      // 遍历所有数值映射，从demands数组中同步输入值
      this.numericalMappings.forEach(mapping => {
        // 查找对应的需求
        const matchingDemand = this.demands.find(d =>
          d.id === mapping.id ||
          (d.sdid && d.sdid === mapping.sdid)
        );

        if (matchingDemand && matchingDemand.inputValue !== undefined) {
          // 处理数值类型 - 保留小数
          if (typeof matchingDemand.inputValue === 'string') {
            // 处理特殊值：无穷
            if (matchingDemand.inputValue === 'Infinity' || matchingDemand.inputValue === '∞') {
              mapping.inputValue = Infinity;
            } else if (matchingDemand.inputValue === '-Infinity' || matchingDemand.inputValue === '-∞') {
              mapping.inputValue = -Infinity;
            } else {
              // 字符串形式的数值转为浮点数
              mapping.inputValue = parseFloat(matchingDemand.inputValue) || 0;
            }
          } else {
            // 直接使用数值 - 不需要转换
            mapping.inputValue = matchingDemand.inputValue;
          }

          console.log(`同步需求 "${mapping.name}" 的输入值: ${mapping.inputValue}`);
        }
      });
    },

    // 获取输入的最小值
    getMinValue(demand) {
      // 如果有范围设置，获取范围的最小值
      if (demand.selectedRange) {
        const parts = demand.selectedRange.split('-');
        const minText = parts[0].trim();

        if (minText === '-∞' || minText === 'Infinity') {
          return -Infinity; // 允许负无穷
        }

        return parseFloat(minText);
      }

      // 默认最小值设为负无穷
      return -Infinity;
    },

    // 获取输入的最大值
    getMaxValue(demand) {
      // 如果有范围设置，获取范围的最大值
      if (demand.selectedRange) {
        const parts = demand.selectedRange.split('-');
        const maxText = parts[1].trim();

        if (maxText === '∞' || maxText === 'Infinity') {
          return Infinity; // 允许正无穷
        }

        return parseFloat(maxText);
      }

      // 默认最大值设为正无穷
      return Infinity;
    },

    // 处理数值输入变化
    handleNumberInputChange(demand, value) {
      // 保存原始输入值
      demand.inputValue = value;

      // 如果需要验证范围，可以在这里添加

      // 更新计算
      this.syncInputValues();
      this.calculateNumericalIndicators();
    },

    // 处理输入特殊值
    handleSpecialValueInput(demand, type) {
      if (type === 'infinity') {
        demand.inputValue = Infinity;
        demand.displayValue = '∞';
      } else if (type === '-infinity') {
        demand.inputValue = -Infinity;
        demand.displayValue = '-∞';
      }

      // 更新计算
      this.syncInputValues();
      this.calculateNumericalIndicators();
    },

    // 处理范围类型选择
    handleRangeChange(demand, rangeValue) {
      console.log(`选择了范围: ${rangeValue} 用于需求: ${demand.name}`);

      // 提取范围值
      let minValue, maxValue;

      if (rangeValue) {
        const rangeParts = rangeValue.split('-');
        minValue = rangeParts[0].trim();
        maxValue = rangeParts[1].trim();

        // 处理无穷
        if (minValue === '∞' || minValue === 'Infinity') minValue = Infinity;
        else if (minValue === '-∞' || minValue === '-Infinity') minValue = -Infinity;
        else minValue = parseFloat(minValue);

        if (maxValue === '∞' || maxValue === 'Infinity') maxValue = Infinity;
        else if (maxValue === '-∞' || maxValue === '-Infinity') maxValue = -Infinity;
        else maxValue = parseFloat(maxValue);

        // 计算中间值作为默认输入值
        if (isFinite(minValue) && isFinite(maxValue)) {
          demand.inputValue = ((minValue + maxValue) / 2).toFixed(2);
        } else if (isFinite(minValue)) {
          // 当最大值是无穷时取最小值的2倍
          demand.inputValue = (minValue * 2).toFixed(2);
        } else if (isFinite(maxValue)) {
          // 当最小值是无穷时取最大值的一半
          demand.inputValue = (maxValue / 2).toFixed(2);
        } else {
          // 两边都是无穷的情况
          demand.inputValue = "0";
        }
      }

      demand.selectedRange = rangeValue;
    },

    // 获取链上状态标签类型
    getChainStatusTagType(status) {
      if (status === 'CONFIRMED') {
        return 'success';
      } else if (status === 'PENDING') {
        return 'warning';
      } else if (status === 'FAILED') {
        return 'danger';
      } else {
        return 'info';
      }
    },

    // 获取链上状态显示文本
    getChainStatusText(status) {
      if (status === 'CONFIRMED') {
        return '已上链';
      } else if (status === 'PENDING') {
        return '上链中';
      } else if (status === 'FAILED') {
        return '上链失败';
      } else {
        return '未上链';
      }
    },
  }
};
</script>

<style lang="scss" scoped>
// 整体容器样式
.app-container {
  background-color: #fafbfc;
  border-radius: 4px;
  padding: 20px 24px;
  box-shadow: 0 1px 8px rgba(0, 0, 0, 0.03);
}

// 分割面板样式
.default-theme {
  height: calc(100vh - 180px);
  min-height: 600px;
}

// 面板容器样式
.panel-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  background-color: #fff;
  border-radius: 4px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.05);
}

// 面板头部样式
.panel-header {
  padding: 14px 20px;
  font-weight: bold;
  font-size: 16px;
  color: #17233d;
  border-bottom: 1px solid #e8eaec;
  display: flex;
  align-items: center;
}

// 搜索框样式
.search-box {
  padding: 10px;
  background: #f8f8f9;
}

// 面板内容区域样式
.panel-body {
  flex: 1;
  padding: 10px;
  overflow: auto;
}

// 树节点样式
.tree-node-name {
  display: inline-flex !important;
  align-items: center;

  .node-icon {
    margin-right: 8px;
    font-size: 16px;

    &.el-icon-folder {
      color: #E6A23C;
    }

    &.el-icon-document {
      color: #409EFF;
    }
  }
}

// 树缩进调整
::v-deep .el-tree__indent {
  padding-left: 16px !important;
}

// 内容容器样式
.content-container {
  height: 100%;
  background-color: #fff;
  border-radius: 4px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
  display: flex;
  flex-direction: column;
}

// 内容标题样式
.panel-header {
  justify-content: space-between;

  .main-title {
    font-size: 18px;
    font-weight: 600;
    color: #17233d;
  }

  .sub-title {
    font-size: 14px;
    color: #808695;
    margin-left: 12px;
    background-color: #f8f8fc;
    padding: 2px 8px;
    border-radius: 4px;
  }

  .header-actions {
    display: flex;
    gap: 10px;
  }
}

// 按钮样式
.action-button {
  border-radius: 3px;
  transition: all 0.2s;
  font-weight: 400;
  font-size: 12px;
  padding: 8px 15px;

  i {
    margin-right: 4px;
  }
}

.add-btn {
  background-color: #0960bd;
  border: 1px solid #0960bd;
  color: #fff;

  &:hover {
    background-color: #0854a9;
    border-color: #0854a9;
  }
}

.expand-btn {
  background-color: #f2f3f5;
  border: 1px solid #dcdfe6;
  color: #606266;

  &:hover, &:focus {
    background-color: #e9ebef;
    color: #333;
  }
}

// 内容区域样式
.content-body {
  flex: 1;
  padding: 16px;
  overflow: auto;
  display: flex;
  position: relative;
}

// 转换按钮容器
.conversion-button-container {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 10;
  transition: all 0.5s cubic-bezier(0.23, 1, 0.32, 1); /* 添加缓动效果 */
}

// 带标签的按钮结构
.button-with-label {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

// 按钮标签
.button-label {
  font-size: 16px;
  font-weight: 600;
  color: #0050e0;
  background-color: rgba(255, 255, 255, 0.95);
  padding: 4px 12px;
  border-radius: 4px;
  box-shadow: 0 2px 6px rgba(0, 80, 224, 0.2);
  margin-top: 6px;
  letter-spacing: 1px;
  position: relative;
  overflow: hidden;

  &:after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, #0050e0, transparent);
  }
}

// 转换按钮
.conversion-button {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  padding: 0;
  font-size: 20px;
  background: linear-gradient(135deg, #1a6dff 0%, #0050e0 100%);
  border: none;
  box-shadow: 0 4px 12px rgba(0, 80, 224, 0.3);
  transition: all 0.3s;

  i {
    margin: 0; // 移除图标的右侧边距
  }

  &:hover {
    transform: scale(1.1);
    box-shadow: 0 6px 16px rgba(0, 80, 224, 0.4);
  }

  &:active {
    transform: scale(0.95);
  }

  &:disabled {
    background: #c0c4cc;
    box-shadow: none;
  }
}

// 需求和指标面板样式
.requirements-panel, .indicators-panel {
  height: 100%;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid #ebeef5;
}

// 选区标题样式
.section-header {
  padding: 14px 20px;
  font-size: 16px;
  font-weight: 500;
  color: #17233d;
  background: linear-gradient(to right, #f8f8fc, #ffffff);
  border-bottom: 1px solid #e8eaec;
  display: flex;
  align-items: center;

  i {
    margin-right: 8px;
    font-size: 18px;
    color: #2d8cf0;
  }

  .count-tag {
    margin-left: 8px;
    background-color: #f0f2f5;
    color: #606266;
    border: none;
  }
}

// 面板内容样式
.panel-content {
  flex: 1;
  padding: 0;
  overflow: auto;
}

// 需求文本框样式
.requirements-text-boxes {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
}

.requirement-text-box {
  background-color: #fff;
  border-left: 3px solid #409EFF;
  border-radius: 4px;
  padding: 14px 18px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  transition: all 0.3s;
  position: relative;

  &::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    border-radius: 4px;
    border: 1px solid #e8e9eb;
    pointer-events: none;
  }

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  }
}

.requirement-name {
  font-weight: 600;
  color: #303133;
  margin-right: 8px;
  font-size: 14px;
}

.requirement-value {
  color: #606266;
  font-size: 14px;

  &:empty::after {
    content: '无值';
    color: #909399;
    font-style: italic;
  }
}

// 技术指标文本框样式
.indicator-box {
  position: relative;
  padding-bottom: 24px; /* 为来源信息预留空间 */
  margin-bottom: 12px;
  word-break: break-all; /* 确保长文本会换行 */
  overflow: hidden; /* 防止内容溢出 */
  transition: all 0.3s ease; /* 添加过渡效果 */

  &.direct-mapping {
    border-left: 3px solid #909399; /* 灰色边框 */

    .requirement-name {
      color: #606266;
    }
  }

  &.knowledge-mapping {
    border-left: 3px solid #67C23A; /* 绿色边框 */

    .requirement-name {
      color: #2c7;
    }
  }
}

.indicator-content {
  display: flex;
  flex-direction: row; /* 行内排列 */
  width: 100%;
  padding-right: 10px; /* 确保内容不会贴边 */
  flex-wrap: wrap; /* 允许在必要时换行 */
  align-items: baseline; /* 基线对齐 */
}

.requirement-name {
  font-weight: bold;
  margin-right: 6px; /* 名称和值之间的间距 */
  white-space: nowrap; /* 名称不换行 */
}

.requirement-value {
  flex: 1; /* 值部分占据剩余空间 */
  word-break: break-word; /* 允许在单词内换行，确保不会溢出 */
  line-height: 1.4;
  margin-right: 8px; /* 给标签留出空间 */
}

.indicator-tag {
  margin-left: auto; /* 将标签推到最右侧 */
  align-self: flex-start; /* 对齐到顶部 */
  margin-top: 2px; /* 微调位置 */
}

.indicator-source {
  position: absolute;
  bottom: 4px;
  left: 18px;
  font-size: 12px;
  color: #909399;
  width: calc(100% - 36px); /* 减去左右内边距 */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;

  .source-info {
    font-style: italic;
  }
}

.indicator-stats {
  margin-left: auto;
  display: flex;
  gap: 8px;
}

// 合同预览区域样式
.contract-preview {
  margin-top: 20px;
  background-color: #fff;
  border-radius: 4px;
  box-shadow: 0 1px 8px rgba(0, 0, 0, 0.05);
  display: flex;
  flex-direction: column;
}

.preview-content {
  padding: 16px;
  min-height: 200px;
  max-height: 400px;
  overflow: auto;
}

.contract-content {
  padding: 20px;
  background-color: #f9f9f9;
  border-radius: 4px;
  border: 1px solid #ebeef5;
}

.contract-html {
  font-family: 'SimSun', serif;
  line-height: 1.7;
  color: #333;
}

.no-value {
  color: #999;
  font-style: italic;
}

// 需求下拉框样式
.requirement-dropdown {
  display: flex;
  align-items: center;
  width: 100%;

  .requirement-select {
    flex: 1;
    margin-left: 8px;
  }
}

.el-select .el-input__inner {
  border-color: #e8eaec;
  background-color: #fff;

  &:hover, &:focus {
    border-color: #409EFF;
  }
}

.requirement-text-box {
  // ... existing styles ...

  &.has-options {
    background-color: #f0f9ff;
    border-left-color: #1890ff;

    &:hover {
      background-color: #e6f7ff;
    }
  }
}

/* 添加进入和离开的动画效果 */
.indicator-transition-enter-active,
.indicator-transition-leave-active {
  transition: all 0.5s;
}

.indicator-transition-enter {
  opacity: 0;
  transform: translateY(20px);
}

.indicator-transition-leave-to {
  opacity: 0;
  transform: translateY(-20px);
}

/* 添加转换面板的过渡效果 */
.transform-panel-enter-active,
.transform-panel-leave-active {
  transition: opacity 0.5s, transform 0.5s;
}

.transform-panel-enter,
.transform-panel-leave-to {
  opacity: 0;
  transform: scale(0.95);
}

/* 转换按钮点击效果 */
.transform-btn {
  transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1);
}

.transform-btn:active {
  transform: scale(0.95);
}

.success-info {
  text-align: center;
  padding: 20px 0;
}

.success-icon {
  font-size: 60px;
  color: #67C23A;
  margin-bottom: 20px;
}

.success-message {
  font-size: 20px;
  font-weight: bold;
  color: #303133;
  margin-bottom: 15px;
}

.contract-info {
  background-color: #f5f7fa;
  border-radius: 4px;
  padding: 15px;
  margin: 15px 0;
  text-align: left;

  p {
    margin: 5px 0;
    color: #606266;
  }
}

/* Add these styles to the <style> section */
.numerical-input {
  background-color: #f0f9ff;
  border-left: 3px solid #409EFF;
}

.requirement-numerical {
  display: flex;
  flex-direction: column; /* Change to column layout for consistency */
  width: 100%;

  .requirement-name {
    font-weight: 600;
    color: #303133;
    margin-bottom: 8px; /* Add space between name and input */
    font-size: 14px;
  }

  .numerical-input-container {
    display: flex;
    align-items: center;
    width: 100%;
  }

  .numerical-input {
    width: 220px; /* Increased from 150px to 220px */
  }

  .unit-label {
    margin-left: 8px;
    color: #606266;
    font-size: 14px;
  }

  .formula-info {
    margin-left: 8px;
    color: #409EFF;
    cursor: pointer;
  }
}

/* 计算型指标特殊样式 */
.indicator-box.calculation {
  border-left: 3px solid #E6A23C !important; /* 橙色边框 */
  background-color: #fdf6ec !important; /* 淡橙色背景 */
}

.indicator-box.calculation .requirement-name {
  color: #E6A23C !important; /* 橙色文本 */
}

.indicator-box.calculation .indicator-tag {
  background-color: #E6A23C !important;
  color: white !important;
}

.sources-popover {
  max-height: 300px;
  overflow-y: auto;

  .source-title {
    font-weight: bold;
    margin-bottom: 8px;
    color: #303133;
    border-bottom: 1px solid #eee;
    padding-bottom: 5px;
  }

  .source-item {
    margin-bottom: 8px;
    padding-bottom: 8px;
    border-bottom: 1px dashed #eee;
    display: flex;
    flex-wrap: wrap;
    align-items: center;

    &:last-child {
      border-bottom: none;
      margin-bottom: 0;
    }

    .source-demand {
      font-weight: 500;
      margin-right: 8px;
    }

    .source-value {
      color: #606266;
      margin-right: 8px;
      font-style: italic;
    }
  }
}

.multiple-sources {
  display: flex;
  align-items: center;
  cursor: pointer;
  color: #409EFF;

  .el-icon-info {
    margin-left: 4px;
  }
}

/* 添加分组显示样式 */
.item-group {
  margin-bottom: 16px;
  border-radius: 4px;
  overflow: hidden;
  background-color: #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
  border: 1px solid #ebeef5;
}

.group-header {
  display: flex;
  align-items: center;
  padding: 10px 16px;
  background-color: #f5f7fa;
  cursor: pointer;
  transition: all 0.3s;

  &:hover {
    background-color: #edf2fc;
  }
}

.group-title {
  font-weight: 600;
  font-size: 14px;
  color: #303133;
  margin-left: 8px;
}

.group-count {
  margin-left: 8px;
  background-color: rgba(144, 147, 153, 0.1);
  border: none;
}

.collapse-icon {
  color: #409EFF;
  transition: transform 0.3s;
}

.group-content {
  padding: 0;
  overflow: hidden;
  transition: all 0.3s;
}

/* 改进小数输入框样式 */
.numerical-input {
  width: 220px; /* Increased from 150px to 220px */

  /* 确保允许小数点输入 */
  ::v-deep .el-input-number__decrease,
  ::v-deep .el-input-number__increase {
    background-color: #f5f7fa;
    width: 24px;
    height: 32px; /* Match input height */
    line-height: 32px;
  }

  ::v-deep .el-input__inner {
    padding-right: 25px; /* 为右侧控制按钮留出空间 */
    text-align: right;  /* 数字右对齐 */
    font-family: 'Arial', sans-serif; /* 使用等宽字体显示数字 */
    -moz-appearance: textfield; /* 移除Firefox默认的上下箭头 */
    height: 32px; /* Add fixed height */
    line-height: 32px;
  }

  /* 移除Chrome中的上下箭头 */
  ::v-deep input::-webkit-outer-spin-button,
  ::v-deep input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
  }
}

/* 数值需求文本框统一样式 */
.requirement-text-box.numerical-input {
  background-color: #fff; /* Match text field background */
  border-left: 3px solid #409EFF;
  padding: 14px 18px; /* Match text field padding */
}
</style>
